package com.pureut.order.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pureut.common.core.exception.GlobalException;
import com.pureut.common.core.utils.bean.BeanUtils;
import com.pureut.common.core.web.domain.AjaxResult;
import com.pureut.common.security.utils.DictUtils;
import com.pureut.common.security.utils.SecurityUtils;
import com.pureut.order.domain.CustomerManagement;
import com.pureut.order.domain.SalesOrder;
import com.pureut.order.domain.SalesOrderDetail;
import com.pureut.order.domain.system.domain.MaterialAwmateria;
import com.pureut.order.domain.system.domain.MaterialFinished;
import com.pureut.order.domain.system.domain.MaterialHalf;
import com.pureut.order.domain.system.domain.MaterialWaste;
import com.pureut.order.dto.DetailViewDto;
import com.pureut.order.dto.SalesOrderDetailDto;
import com.pureut.order.dto.SalesOrderDetailViewDto;
import com.pureut.order.dto.SalesOrderDto;
import com.pureut.order.mapper.SalesOrderDetailMapper;
import com.pureut.order.mapper.SalesOrderMapper;
import com.pureut.order.service.CustomerManagementService;
import com.pureut.order.service.SalesOrderDetailService;
import com.pureut.order.service.SalesOrderService;
import com.pureut.order.vo.GenerateInvoiceListVo;
import com.pureut.order.vo.GenerateInvoiceVo;
import com.pureut.order.vo.OrderReviewVo;
import com.pureut.order.vo.SalesOrderDetailVo;
import com.pureut.system.api.FeignService;
import com.pureut.system.api.SchedulingPlanFeignService;
import com.pureut.system.api.StorageFegin;
import com.pureut.system.api.domain.SysDictData;
import com.pureut.system.api.vo.PickingSaleRelationVo;
import com.pureut.system.api.vo.PickingSaleVo;
import com.pureut.system.api.vo.SysAuditHistoryVo;
import com.pureut.system.api.vo.UpdateSaleVo;
import org.hibernate.validator.internal.util.stereotypes.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.lang.Double.doubleToLongBits;

/***
 *
 * Author:C
 * Date:2022/12/01 10:56
 * @DESC
 */
@Service
public class SalesOrderDetailServiceImpl extends ServiceImpl<SalesOrderDetailMapper, SalesOrderDetail> implements SalesOrderDetailService {

    @Lazy
    @Resource
    SalesOrderDetailMapper salesOrderDetailMapper;

    @Lazy
    @Resource
    SalesOrderService salesOrderService;

    @Resource
    FeignService feignService;

    @Resource
    CustomerManagementService customerManagementService;

    @Resource
    StorageFegin storageFegin;

    @Resource
    SalesOrderMapper salesOrderMapper;

    //排程
    @Resource
    SchedulingPlanFeignService schedulingPlanFeignService;

    /**
     * 获取销售订单明细列表
     *
     * @param id
     * @return
     */
    @Override
    public List<SalesOrderDetailDto> getList(Long id) {

        //获取明细列表
        List<SalesOrderDetailDto> detailList = salesOrderDetailMapper.getDetailList(id);
        //获取销售订单明细状态缓存字典数据
        List<SysDictData> statusArray = DictUtils.getDictCache("sales_order_detail_status");
        Map<String, String> actualMap = statusArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取网型标准缓存字典数据
        List<SysDictData> netArray = DictUtils.getDictCache("sys_of_type");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取铺网类型标准缓存字典数据
        List<SysDictData> netTypeArray = DictUtils.getDictCache("sys_type_net");
        Map<String, String> netTypeMap = netTypeArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取质量标准缓存字典数据
        List<SysDictData> standardArray = DictUtils.getDictCache("sale_order_quality_standard");
        Map<String, String> qualityMap = standardArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        for (SalesOrderDetailDto entity : detailList) {

            entity.setOrderDetailStatusDict(actualMap.get(entity.getOrderDetailStatus()));
            entity.setMaterialNetTypeDict(netTypeMap.get(String.valueOf(entity.getMaterialNetType())));
            entity.setMaterialNetDict(netMap.get(String.valueOf(entity.getMaterialNet())));
            entity.setQualityStandardDict(qualityMap.get(entity.getQualityStandard()));
        }
        return detailList;
    }

    /**
     * 查看明细
     *
     * @param id
     * @return
     */
    @Override
    public SalesOrderDetailDto getView(Long id) {
        //获取明细信息
//        SalesOrderDetail salesOrderDetail = getById(id);
        SalesOrderDetailDto viewById = salesOrderDetailMapper.getViewById(id);
        //获取订单信息
        SalesOrder salesOrder = salesOrderService.getById(viewById.getSalesOrderId());
        SalesOrderDetailDto salesOrderDetailDto = new SalesOrderDetailDto();
        BeanUtils.copyProperties(viewById, salesOrderDetailDto);
        //获取网型标准缓存字典数据
        List<SysDictData> netArray = DictUtils.getDictCache("sys_of_type");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取铺网类型标准缓存字典数据
        List<SysDictData> netTypeArray = DictUtils.getDictCache("sys_type_net");
        Map<String, String> netTypeMap = netTypeArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取质量标准缓存字典数据
        List<SysDictData> standardArray = DictUtils.getDictCache("sale_order_quality_standard");
        Map<String, String> qualityMap = standardArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取纸管小卷数字典数据
        List<SysDictData> rollsArray = DictUtils.getDictCache("sale_order_number_rolls");
        Map<String, String> numberMap = rollsArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取偏差字典数据
        List<SysDictData> deviationArray = DictUtils.getDictCache("sale_order_deviation");
        Map<String, String> deviationMap = deviationArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取包装字典数据
        List<SysDictData> packArray = DictUtils.getDictCache("sale_order_packing");
        Map<String, String> packMap = packArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取明细状态字典数据
        List<SysDictData> statusArray = DictUtils.getDictCache("sales_order_detail_status");
        Map<String, String> statusMap = statusArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        List<SalesOrderDetailViewDto> salesOrderDetailViewDtoList = new ArrayList<>();
        SalesOrderDetailViewDto salesOrderDetailViewDto = new SalesOrderDetailViewDto();
        salesOrderDetailDto.setId(salesOrder.getId());
        //获取客户信息
        CustomerManagement byId = customerManagementService.getById(salesOrder.getCustomerId());
        salesOrderDetailDto.setCustomerName(byId.getCustomerName());
        salesOrderDetailDto.setCustomerId(salesOrder.getCustomerId());
        //获取订单类别字典值
        List<SysDictData> typeArray = DictUtils.getDictCache("sales_order_type");
        Map<String, String> orderTypeMap = typeArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        salesOrderDetailDto.setOrderTypeDict(orderTypeMap.get(String.valueOf(salesOrder.getOrderType())));
        salesOrderDetailDto.setOrderType(String.valueOf(salesOrder.getOrderType()));
        //获取订单优先级字典值
        List<SysDictData> priorityArray = DictUtils.getDictCache("sales_order_priority");
        Map<String, String> orderpriorityArrayMap = priorityArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        salesOrderDetailDto.setOrderPriorityDict(orderpriorityArrayMap.get(String.valueOf(salesOrder.getOrderPriority())));
        salesOrderDetailDto.setOrderPriority(String.valueOf(salesOrder.getOrderPriority()));
        //备注
        salesOrderDetailDto.setRemark(salesOrder.getRemark());
        //文件
        salesOrderDetailDto.setContractUrl(salesOrder.getContractUrl());
        //退回原因
        salesOrderDetailDto.setBackReason(salesOrder.getBackReason());
        //终止原因
        salesOrderDetailDto.setStopReason(salesOrder.getStopReason());
        //销售订单号
        salesOrderDetailDto.setSalesOrderNum(salesOrder.getSalesOrderNum());
        //销售合同号
        salesOrderDetailDto.setSalesContractNum(salesOrder.getSalesContractNum());

        salesOrderDetailViewDto.setMaterialName(viewById.getMaterialName());
            salesOrderDetailViewDto.setMaterialCode(viewById.getMaterialCode());
            salesOrderDetailViewDto.setMaterialSpec(viewById.getMaterialSpec());
            salesOrderDetailViewDto.setMaterialNet(String.valueOf(viewById.getMaterialNet()));
            salesOrderDetailViewDto.setMaterialNetType(String.valueOf(viewById.getMaterialNetType()));
            salesOrderDetailViewDto.setMaterialNetTypeDict(netTypeMap.get(String.valueOf(viewById.getMaterialNetType())));
            salesOrderDetailViewDto.setMaterialNetDict(netMap.get(String.valueOf(viewById.getMaterialNet())));
            salesOrderDetailViewDto.setMaterialRatio(viewById.getMaterialRatio());
            salesOrderDetailViewDto.setMaterialGheavy(viewById.getMaterialGheavy());
        salesOrderDetailViewDto.setId(viewById.getId());
        salesOrderDetailViewDto.setWidthCloth(viewById.getWidthCloth());
        salesOrderDetailViewDto.setDeviationValue(viewById.getDeviationValue());
        salesOrderDetailViewDto.setDeliveryDate(viewById.getDeliveryDate());
        salesOrderDetailViewDto.setRollDiameter(viewById.getRollDiameter());
        salesOrderDetailViewDto.setThickness(viewById.getThickness());
        salesOrderDetailViewDto.setUnitPrice(viewById.getUnitPrice());
        salesOrderDetailViewDto.setPlanWeight(viewById.getPlanWeight());
        salesOrderDetailViewDto.setQualityStandard(String.valueOf(viewById.getQualityStandard()));
        salesOrderDetailViewDto.setQualityStandardDict(qualityMap.get(String.valueOf(viewById.getQualityStandard())));
        salesOrderDetailViewDto.setNumberRolls(String.valueOf(viewById.getNumberRolls()));
        salesOrderDetailViewDto.setNumberRollsDict(numberMap.get(String.valueOf(viewById.getNumberRolls())));
        salesOrderDetailViewDto.setDeviation(String.valueOf(viewById.getDeviation()));
        salesOrderDetailViewDto.setDeviationDict(deviationMap.get(String.valueOf(viewById.getDeviation())));
        salesOrderDetailViewDto.setPacking(String.valueOf(viewById.getPacking()));
        salesOrderDetailViewDto.setPackingDict(packMap.get(String.valueOf(viewById.getPacking())));
        salesOrderDetailViewDto.setOrderDetailStatus(String.valueOf(viewById.getOrderDetailStatus()));
        salesOrderDetailViewDto.setOrderDetailStatusDict(statusMap.get(String.valueOf(viewById.getOrderDetailStatus())));
        //已发货重量
        salesOrderDetailViewDto.setProducedWeight(viewById.getProducedWeight());
        //已生产重量
        salesOrderDetailViewDto.setShippingWeight(viewById.getShippingWeight());
        salesOrderDetailViewDtoList.add(salesOrderDetailViewDto);
        salesOrderDetailDto.setSalesOrderDetailDtoList(salesOrderDetailViewDtoList);
        return salesOrderDetailDto;
    }

    /**
     * 修改
     *
     * @param salesOrderDetailVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSalesOrderDetail(SalesOrderDetailVo salesOrderDetailVo) {
        SalesOrderDetail salesOrderDetail = getById(salesOrderDetailVo.getId());
        //获取订单数据
        SalesOrder salesOrder = salesOrderMapper.selectOne(new QueryWrapper<SalesOrder>().lambda().eq(SalesOrder::getId, salesOrderDetail.getSalesOrderId()));
        if (1 == salesOrderDetail.getOrderDetailStatus() || 5 == salesOrderDetail.getOrderDetailStatus() || 7 == salesOrderDetail.getOrderDetailStatus()) {
            if (5 == salesOrderDetail.getOrderDetailStatus() || 7 == salesOrderDetail.getOrderDetailStatus()) {
                salesOrderDetail.setWidthCloth(salesOrderDetailVo.getWidthCloth());
                salesOrderDetail.setDeviationValue(salesOrderDetailVo.getDeviationValue());
                salesOrderDetail.setDeliveryDate(salesOrderDetailVo.getDeliveryDate());
                salesOrderDetail.setRollDiameter(salesOrderDetailVo.getRollDiameter());
                salesOrderDetail.setThickness(salesOrderDetailVo.getThickness());
                salesOrderDetail.setUnitPrice(salesOrderDetailVo.getUnitPrice());
                salesOrderDetail.setPlanWeight(salesOrderDetailVo.getPlanWeight());
                salesOrderDetail.setQualityStandard(Integer.parseInt(salesOrderDetailVo.getQualityStandard()));
                salesOrderDetail.setNumberRolls(Integer.parseInt(salesOrderDetailVo.getNumberRolls()));
                salesOrderDetail.setDeviation(Integer.parseInt(salesOrderDetailVo.getDeviation()));
                salesOrderDetail.setPacking(Integer.parseInt(salesOrderDetailVo.getPacking()));

                if (7 == salesOrderDetail.getOrderDetailStatus()){
                    //如果是退回状态将明细状态更新为进行中，排程状态更新为待确认
                    salesOrderDetail.setOrderDetailStatus(9);
                    com.pureut.system.api.vo.SalesOrderDetailVo salesData = new com.pureut.system.api.vo.SalesOrderDetailVo();
                    BeanUtils.copyProperties(salesOrderDetail,salesData);
                    UpdateSaleVo updateSaleVo = new UpdateSaleVo();
                    updateSaleVo.setMaterialCode(salesOrderDetail.getMaterialCode());
                    updateSaleVo.setSaleId(salesOrderDetail.getSalesOrderId());
                    updateSaleVo.setStatus("1");
                    updateSaleVo.setSalesData(salesData);
                    boolean b = schedulingPlanFeignService.updatePlanStatusUnit(updateSaleVo);
                    if (!b){
                        throw new GlobalException("服务调用失败");
                    }
                }

                //调用审核
                if (salesOrderDetail.getOrderDetailStatus() == 5) {
                    SysAuditHistoryVo sysAuditHistoryVo = new SysAuditHistoryVo();
                    String perms = "order:sale:saleOrder:examine";
                    String auditDoc = salesOrder.getSalesOrderNum() + salesOrderDetail.getId();
                    sysAuditHistoryVo.setAuditDoc(auditDoc);
                    sysAuditHistoryVo.setPerms(perms);
                    AjaxResult history = feignService.editHistory(sysAuditHistoryVo);
                    String code = JSON.parseObject(JSON.toJSONString(history.get("code")), String.class);
                    if ("200".equals(code)) {
                        salesOrderDetail.setOrderDetailStatus(2);
                        return updateById(salesOrderDetail);
                    } else {
                        return false;
                    }
                }
                return updateById(salesOrderDetail);
            } else {
                salesOrderDetail.setWidthCloth(salesOrderDetailVo.getWidthCloth());
                salesOrderDetail.setDeviationValue(salesOrderDetailVo.getDeviationValue());
                salesOrderDetail.setDeliveryDate(salesOrderDetailVo.getDeliveryDate());
                salesOrderDetail.setRollDiameter(salesOrderDetailVo.getRollDiameter());
                salesOrderDetail.setThickness(salesOrderDetailVo.getThickness());
                salesOrderDetail.setUnitPrice(salesOrderDetailVo.getUnitPrice());
                salesOrderDetail.setPlanWeight(salesOrderDetailVo.getPlanWeight());
                salesOrderDetail.setQualityStandard(Integer.parseInt(salesOrderDetailVo.getQualityStandard()));
                salesOrderDetail.setNumberRolls(Integer.parseInt(salesOrderDetailVo.getNumberRolls()));
                salesOrderDetail.setDeviation(Integer.parseInt(salesOrderDetailVo.getDeviation()));
                salesOrderDetail.setPacking(Integer.parseInt(salesOrderDetailVo.getPacking()));
                return updateById(salesOrderDetail);
            }
        }
        return false;
    }

    /**
     * 根据订单id和物料编码查询销售明细
     *
     * @param salesOrderId, String materialCode
     * @return
     */
    @Override
    public DetailViewDto getDetailById(Long salesOrderId, String materialCode) {

        DetailViewDto viewDto = new DetailViewDto();
        SalesOrderDetail one = getOne(new QueryWrapper<SalesOrderDetail>().lambda().eq(SalesOrderDetail::getSalesOrderId, salesOrderId).eq(SalesOrderDetail::getMaterialCode, materialCode));
        if (one != null) {
            viewDto.setWidthCloth(one.getWidthCloth());
            viewDto.setThickness(one.getThickness());
            viewDto.setNumberRolls(one.getNumberRolls());
            viewDto.setRollDiameter(one.getRollDiameter());
            //获取包装字典数据
            List<SysDictData> packArray = DictUtils.getDictCache("sale_order_packing");
            Map<String, String> packMap = packArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
            viewDto.setPacking(one.getPacking());
            String s = String.valueOf(one.getPacking());
            viewDto.setPackingDict(packMap.get(s));
            SalesOrder salesOrder = salesOrderService.getById(salesOrderId);
            viewDto.setRemark(salesOrder.getRemark());
            viewDto.setContractUrl(salesOrder.getContractUrl());
        } else {
            throw new GlobalException("查询的数据不存在");
        }
        return viewDto;
    }

    /**
     * 生成发货单
     *
     * @param generateInvoiceVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateInvoice(GenerateInvoiceVo generateInvoiceVo) {

        //获取明细信息
        SalesOrderDetail byId = getById(generateInvoiceVo.getList().get(0).getId());
        if (byId.getOrderDetailStatus() == 9 || byId.getOrderDetailStatus() == 6) {
            //获取订单信息
            SalesOrder salesOrder = salesOrderService.getById(byId.getSalesOrderId());

            PickingSaleVo pickingSaleVo1 = new PickingSaleVo();

            pickingSaleVo1.setTransceiverType(1);
            pickingSaleVo1.setDateDelivery(new Date());
            pickingSaleVo1.setCustomId(generateInvoiceVo.getCustomId());

            List<GenerateInvoiceListVo> list = generateInvoiceVo.getList();
            //仅“成品”和“半成品”物料的发货重量需小于生产重量，其他类别校验库存重量
            if (salesOrder.getOrderType() == 3 || salesOrder.getOrderType() == 4) {
                //发货重量
                BigDecimal bigDecimal = new BigDecimal(String.valueOf(list.get(0).getPlannedWeight()));
//                long l = doubleToLongBits(list.get(0).getPlannedWeight());
                //生产重量
                BigDecimal bigDecimal1 = new BigDecimal(byId.getPlanWeight());
//                long l1 = doubleToLongBits(Double.parseDouble(byId.getProducedWeight()));
                if (bigDecimal.compareTo(bigDecimal1) > 0) {
                    throw new GlobalException("发货重量不能大于生产重量");
                }
            } else {
                //发货重量需小于库存重量
                String materialCode = byId.getMaterialCode();
                String sum = storageFegin.getSum(materialCode);
                //发货重量
                BigDecimal bigDecimal = new BigDecimal(String.valueOf(list.get(0).getPlannedWeight()));
//                long l = doubleToLongBits(list.get(0).getPlannedWeight());
                //库存重量
                BigDecimal bigDecimal1 = new BigDecimal(sum);
//                long l1 = doubleToLongBits(Double.parseDouble(sum));
                if (bigDecimal.compareTo(bigDecimal1) > 0) {
                    throw new GlobalException("发货重量不能大于库存重量");
                }
            }

            List<PickingSaleRelationVo> pickingSaleRelationVoList = new ArrayList<>();
            for (GenerateInvoiceListVo entity : list) {
                PickingSaleRelationVo pickingSaleRelationVo = new PickingSaleRelationVo();

                pickingSaleRelationVo.setConnectionId(salesOrder.getSalesOrderNum());
                pickingSaleRelationVo.setMaterialCode(entity.getMaterialCode());
                pickingSaleRelationVo.setMaterialId(entity.getMaterialId());
                pickingSaleRelationVo.setPlannedWeight(entity.getPlannedWeight());
                pickingSaleRelationVoList.add(pickingSaleRelationVo);
            }

            pickingSaleVo1.setList(pickingSaleRelationVoList);
            AjaxResult ajaxResult = storageFegin.addSale(pickingSaleVo1);
            String code = ajaxResult.get("code").toString();

            if ("200".equals(code)) {
                byId.setShippingWeight(String.valueOf(list.get(0).getPlannedWeight()));
                return updateById(byId);
            } else {
                return false;
            }
        } else {
            throw new GlobalException("只能操作“进行中”“已终止”状态的数据");
        }
    }

    /**
     * 根据物料编码获取销售订单
     * @param materialCode
     * @return
     */
    @Override
    public List<SalesOrderDto> getOrderByMaterialCode(String materialCode) {

        return salesOrderDetailMapper.getOrderDocmentList(materialCode);
    }
}
